package com.kedeng.yangmuyi.dao;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.kedeng.yangmuyi.exception.ErrorCodes;
import com.kedeng.yangmuyi.exception.SystemException;
import com.kedeng.yangmuyi.model.BaseDO;

/**
 * The Base Hibernate implements
 * 
 * @author rqian
 * 
 */
@Repository
public class BaseDAOImpl implements BaseDAO {

    protected final static Log logger = LogFactory.getLog(BaseDAOImpl.class);

    @Autowired
    private SessionFactory     sessionFactory;



    /**
     * conut all object for the param, and return the number for the count.
     * 
     * @see com.kedeng.yangmuyi.dao.BaseDAO#countAll(java.lang.String)
     */
    public int countAll(String clazz) {
        final String hql = "select count(*) from " + clazz + " as a";
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        query.setMaxResults(1);
        Long count = (Long) query.uniqueResult();
        return count.intValue();
    }



    /**
     * conut the object's sume by hql, and return the number for the count.
     * 
     * @see com.kedeng.yangmuyi.dao.BaseDAO#countQuery(java.lang.String)
     */
    public int countQuery(String hql) {
        final String counthql = hql;
        Query query = getSessionFactory().getCurrentSession().createQuery(counthql);
        query.setMaxResults(1);
        Long count = (Long) query.uniqueResult();
        return count.intValue();
    }



    /**
     * delete object by id.
     * 
     * @see com.kedeng.yangmuyi.dao.BaseDAO#delById(java.lang.Class,
     *      java.lang.String)
     */
    @SuppressWarnings("rawtypes")
    public boolean delById(Class clazz, String id) throws SystemException {
        Session currentSession = getSessionFactory().getCurrentSession();
        try {
            currentSession.delete(currentSession.load(clazz, id));
            return true;
        } catch (Exception e) {
            logger.error(e + "Delete object falied, and the object is " + clazz + ", id is " + id);
            throw new SystemException(ErrorCodes.ERROR_HIBERNATE, "Delete object falied, and the object is " + clazz
                    + ", id is " + id);
        }
    }



    /**
     * list all ojbects and order by id desc.
     * 
     * @see com.kedeng.yangmuyi.dao.BaseDAO#listAll(java.lang.String)
     */
    @SuppressWarnings("unchecked")
    public List<Object> listAll(String clazz) throws SystemException {
        List<Object> list = null;
        try {
            Query query = getSessionFactory().getCurrentSession().createQuery(
                    "from " + clazz + " as a order by a.id desc");
            list = query.list();
        } catch (Exception e) {
            throw new SystemException(ErrorCodes.ERROR_QUERY_NULL, "Can't find the object in database. The class is "
                    + clazz);
        }
        return list;
    }



    @SuppressWarnings("unchecked")
    public List<Object> listAll(String clazz, int pageNo, int pageSize) throws SystemException {
        final int pNo = pageNo;
        final int pSize = pageSize;
        final String hql = "from " + clazz + " as a order by a.id desc";
        List<Object> result = null;
        try {
            Query query = getSessionFactory().getCurrentSession().createQuery(hql);
            query.setMaxResults(pSize);
            query.setFirstResult((pNo - 1) * pSize);
            result = query.list();
            if (!Hibernate.isInitialized(result)) {
                Hibernate.initialize(result);
            }
        } catch (Exception e) {
            throw new SystemException(ErrorCodes.ERROR_QUERY_NULL, "");
        }
        return result;
    }



    /*
     * @SuppressWarnings("rawtypes") public Object loadById(Class clazz,
     * Serializable id) throws SystemException { Object m_obj =
     * getSessionFactory().getCurrentSession().get(clazz, id); if (m_obj ==
     * null) { throw new SystemException(ErrorCodes.ERROR_QUERY_NULL, ""); }
     * else { return m_obj; } }
     */

    @SuppressWarnings("unchecked")
    public Object loadObject(String hql) {
        Object obj = null;
        final String hqlQueryStr = hql;
        Query createQuery = getSessionFactory().getCurrentSession().createQuery(hqlQueryStr);
        List<Object> list = createQuery.list();
        if (list.size() > 0) {
            obj = list.get(0);
        }
        return obj;
    }



    @SuppressWarnings("unchecked")
    public List<Object> query(String hql) {
        final String hqlQueryStr = hql;
        return getSessionFactory().getCurrentSession().createQuery(hqlQueryStr).list();
    }



    @SuppressWarnings("unchecked")
    public List<Object> query(String hql, int pageNo, int pageSize) {
        final int pNo = pageNo;
        final int pSize = pageSize;
        final String queryHQL = hql;
        Query query = getSessionFactory().getCurrentSession().createQuery(queryHQL);
        query.setMaxResults(pSize);
        query.setFirstResult((pNo - 1) * pSize);
        List<Object> result = query.list();
        if (!Hibernate.isInitialized(result)) {
            Hibernate.initialize(result);
        }
        return result;
    }



    public boolean save(Object entry) throws SystemException {
        try {
            getSessionFactory().getCurrentSession().saveOrUpdate(entry);
        } catch (Exception e) {
            logger.error(e + " Entry: " + entry + " function:save");
            throw new SystemException(ErrorCodes.ERROR_HIBERNATE_ADD, "");
        }
        return true;
    }



    public int update(String hql) {
        final String updateHQL = hql;
        return getSessionFactory().getCurrentSession().createQuery(updateHQL).executeUpdate();
    }



    @SuppressWarnings("rawtypes")
    public Object loadById(Class clazz, String id) throws SystemException {
        Object m_obj = getSessionFactory().getCurrentSession().get(clazz, id);
        if (m_obj == null) {
            throw new SystemException(ErrorCodes.ERROR_QUERY_NULL, "");
        } else {
            return m_obj;
        }
    }



    @SuppressWarnings("rawtypes")
    public int getNewestVersion(Class clazz, String id) throws SystemException {
        BaseDO baseDO = (BaseDO) this.loadById(clazz, id);
        if (baseDO != null) {
            return baseDO.getVersion();
        } else {
            throw new SystemException(ErrorCodes.ERROR_NULL_OBJECT, "");
        }

    }



    public boolean update(Object obj) throws SystemException {
        try {
            getSessionFactory().getCurrentSession().update(obj);
        } catch (Exception e) {
            logger.error(e + " obj: " + obj + " function: update");
            throw new SystemException(ErrorCodes.ERROR_HIBERNATE_UPDATE, "");
        }
        return true;
    }



    /**
     * @return the sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }



    /**
     * @param sessionFactory
     *            the sessionFactory to set
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

}
